#!/usr/bin/python
# coding: utf8
import sys
import re
import string
import fire

ip = '2001:dc7:1000::0/120'
subnet = '126'
#s = '2001:dc7:1000:2:3:4:5:6'

def x2d(s):
  # print('In x2d, s:', s)
  # print('int(s, 16):', int(s, 16))
    return '{:d}'.format(int(s, 16))

def d2x(s):
  # print('In d2x, s:', s)
  # print('int(s):', int(s))
    return '{:X}'.format(int(s))

def b2d(s):
  # print('In b2d, s:', s)
  # print('int(s, 2):', int(s, 2))
    return '{:d}'.format(int(s,2))

def d2b(s):
  # print('In d2b, s:', s)
  # print('int(s):', int(s))
    return '{:b}'.format(int(s))

def x2b(s):
  # print('In x2b, s:', s)
  # print('int(x2d(s)):', int(x2d(s)))
    return '{:b}'.format(int(x2d(s)))

def b2x(s):
  # print('In b2x, s:', s)
  # print('int(b2d(s)):', int(b2d(s)))
    return '{:X}'.format(int(b2d(s)))


def IPv6_to_str(ip):
    if ip.find('::') > 0:
        s1, s3 = (''.join([i.zfill(4) for i in part.split(':')]) for part in ip.split('::'))
        s2 = ''.join(['0' for _ in range(32 - len(s1) - len(s3))])
        ip_str = ''.join([s1, s2, s3])
    else:
        print(ip)
        ip_str = ''.join([i.zfill(4) for i in ip.split(':')])

    return ip_str

def bin_str_2_hex(bin_str):
    # q 个二进制, r个16进制
    r, q = divmod(len(bin_str), 4)
  # print('r: {0}, q: {1}'.format(r, q))
    # r1个可以按':'分割的段， q1个单剩的16进制
    r1, q1 = divmod(r, 4)
  # print('r1: {0}, q1: {1}'.format(r1, q1))
    if q == 0:
        bin_lst = [bin_str[i*4:i*4+4] for i in range(r)]
    else:
        bin_lst = [bin_str[i*4:i*4+4] for i in range(r)] + [bin_str[r*4:r*4+q].ljust(4, '0')]
   #end = bin_str[r*4:r*4+q].ljust(4, '0')
  # print('end: ', end)
  # bin_lst = [bin_str[i*4:i*4+4] for i in range(r)] + [end]
  # print('bin_lst:', bin_lst)
 #  hex_lst = map(b2x, bin_lst)
    hex_str = ''.join(map(b2x, bin_lst))
    ip6 = ':'.join([hex_str[i*4:i*4+4] for i in range(r1)] + [''.join(hex_str[r1*4:])])
    print(ip6)

def main():
    if ip.find('/') > 0:
        ipv6, net = ip.split('/')
    else:
        ipv6 = ip
    ip_str = IPv6_to_str(ipv6)
    ip_bin_str = ''.join([x2b(i).zfill(4) for i in list(ip_str)])

    how_many = pow(2, int(subnet) - int(net))
    r, q = divmod(int(subnet), 4)
    r1, q1 = divmod(r, 4)

    net_prefix_bin = ip_bin_str[:int(net)]
    net_len = int(subnet) - int(net)
    net_range_bin_start = ''.join(['0' for _ in range(net_len)])
    net_range_bin_end = ''.join(['1' for _ in range(net_len)])
#   print(net_range_bin_end)
#   bin_str_2_hex(net_prefix_bin + net_range_bin_start)
#   bin_str_2_hex(net_prefix_bin + net_range_bin_end)
    print('net_prefix_bin: ', net_prefix_bin)
    for i in range(how_many):
        bin_str = d2b(i).rjust(net_len, '0')
       #print('bin_str: ', bin_str)
        bin_str_2_hex(net_prefix_bin + bin_str)
   #sys.exit()


    sublen = 128 - int(subnet)
    # 单剩 q 个二进制
    r, q = divmod(sublen, 4)
    print('r:', r)
    print('q:', q)
    # 单剩 q1 个 F; r1个‘FFFF’
    r1, q1 = divmod(r, 4)

    subnet_start_bin = ''.join(['0' for _ in range(sublen)])
#   subnet_start_lst = [b2x(subnet_start_bin[:q])] + map(b2x, ['0000' for _ in range(r)])
    subnet_start = ':'.join([b2x(subnet_start_bin[:q]) + ''.join(['0' for _ in range(q1)])]
                     + ['0000' for _ in range(r1)])
 #  print(subnet_start_bin)
#   print(subnet_start_lst)
    print('subnet_start: ', subnet_start)

    subnet_end_bin = ''.join(['1' for _ in range(sublen)])
#   subnet_end_lst =  [b2x(subnet_end_bin[:q])] + map(b2x, ['1111' for _ in range(r)])
    subnet_end = ':'.join([b2x(subnet_end_bin[:q]) + ''.join(['F' for _ in range(q1)])] 
                    + ['FFFF' for _ in range(r1)])
    
#   print(subnet_end_lst)
    print('subnet_end: ', subnet_end)

if __name__ == '__main__':
    main()
